package com.hedl.practice.diyJava.encryptionandsecurity.key_exchange_algorithm.tmp;

import javax.crypto.KeyAgreement;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

public class Person {
    private final String name;
    private PublicKey publicKey;
    private PrivateKey privateKey;
    private byte[] secretKey;

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public Person(String name) {
        this.name = name;
    }

    //生成本地KeyPair
    public void generateKeyPair(){
        try{
            KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DH");    //密钥对生成器(密钥方法)
            kpGen.initialize(512);      //传入密钥大小
            KeyPair kp = kpGen.generateKeyPair();       //生成的密钥对
            this.privateKey = kp.getPrivate();      //对私钥的引用。
            this.publicKey = kp.getPublic();        //对公钥的引用。
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public void generateSecretKey(byte[] receivedPubKeyBytes){
        try {
            //从byte[]恢复PublicKey
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(receivedPubKeyBytes);   //密钥；使用给定的编码密钥创建新的
            KeyFactory kf = KeyFactory.getInstance("DH");       //请求的密钥算法的名称。
            PublicKey receivedPublicKey = kf.generatePublic(keySpec);       //公钥的规范

            //生成本地密钥    KeyAgreement=>此类提供密钥协议（或密钥交换）协议的功能
            KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");     //请求的密钥协商算法的标准名称
            keyAgreement.init(this.privateKey);     //自己的PrivateKey
            keyAgreement.doPhase(receivedPublicKey,true);   //对方的PublicKey

            //生成SecretKey密钥
            this.secretKey = keyAgreement.generateSecret(); //生成共享密钥并将其返回到新缓冲区。
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }
    }

    public void printKeys(){
        System.out.printf("Name:%s\n",this.name);
        System.out.printf("Private key:%x\n",new BigInteger(1,this.privateKey.getEncoded()));
        System.out.printf("Public key:%x\n",new BigInteger(1,this.publicKey.getEncoded()));
        System.out.printf("Secret key:%x\n",new BigInteger(1,this.secretKey));
    }
}
